/**
 * @brief  TEST_F与TEST_P混合使用
 */

#include <gmock/gmock.h>
#include <gtest/gtest.h>

using namespace testing;
using std::cout;

class Base {
public:
    virtual ~Base()              = default;
    virtual int func(int &value) = 0;
};

class MockBase : public Base {
public:
    MOCK_METHOD1(func, int(int &));
};

#if 0
static MockBase *mock_ = nullptr;

class TestMockBase : public ::testing::Test {
protected:
    static void SetUpTestSuite() { mock_ = new MockBase(); }

    static void TearDownTestSuite() {
        delete mock_;
        cout << "TearDown" << "\n";
    }

    // MockBase *mock_;
};
#endif

class MyParamTest : public ::testing::TestWithParam<int> {
protected:
#if 0  // 每个参数都会重新执行一遍
    void SetUp() override {
        mock_ = new MockBase();
        cout << "SetUp" << "\n";
    }

    void TearDown() override {
        delete mock_;
        mock_ = nullptr;
        cout << "TearDown" << "\n";
    }
    MockBase *mock_;
#else  // 每个TestSuite重新执行一次
    static void SetUpTestSuite() {
        mock_ = new MockBase();
        cout << "SetUp" << "\n";
    }
    static void TearDownTestSuite() {
        delete mock_;
        mock_ = nullptr;
        cout << "TearDown" << "\n";
    }
    static MockBase *mock_;
#endif
};

MockBase *MyParamTest::mock_ = nullptr;

TEST_P(MyParamTest, Test1) {
    int value = GetParam();
    assert(mock_ != nullptr);
    EXPECT_CALL(*mock_, func(_)).WillOnce(DoAll(SetArgReferee<0>(value), Return(value + 1)));
    int target = 0;

    EXPECT_EQ(mock_->func(target), value + 1);
    EXPECT_EQ(target, value);
}

INSTANTIATE_TEST_CASE_P(Test1, MyParamTest, Values(1, 2, 3));  // 会叠加到所有MyParamTest的case上

TEST_P(MyParamTest, Test2) {
    int value = GetParam();
    assert(mock_ != nullptr);
    EXPECT_CALL(*mock_, func(_)).WillOnce(DoAll(SetArgReferee<0>(value), Return(value + 1)));

    int target = 0;
    EXPECT_EQ(mock_->func(target), value + 1);
    EXPECT_EQ(target, value);
}

INSTANTIATE_TEST_SUITE_P(Test2, MyParamTest, Range(1, 10, 2));  // 会叠加到所有MyParamTest的case上